package com.demo.zyt.modules.app.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.demo.zyt.common.dto.user.AreaNoHaveValueDTO;
import com.demo.zyt.common.dto.user.AreaSelectDTO;
import com.demo.zyt.common.dto.user.WxApplyAllianceDTO;
import com.demo.zyt.common.dto.user.WxInvitedEmailDTO;
import com.demo.zyt.common.dto.user.WxQrcodeDTO;
import com.demo.zyt.common.dto.user.WxUserDTO;
import com.demo.zyt.common.exception.RRException;
import com.demo.zyt.common.utils.AppResultEnum;
import com.demo.zyt.common.utils.PageUtils;
import com.demo.zyt.common.utils.R;
import com.demo.zyt.common.utils.RedisKeys;
import com.demo.zyt.common.utils.RedisUtils;
import com.demo.zyt.common.utils.SmsUtils;
import com.demo.zyt.config.ConfigConstant;
import com.demo.zyt.modules.app.annotation.Login;
import com.demo.zyt.modules.app.annotation.LoginUser;
import com.demo.zyt.modules.app.config.AccessTokenStore;
import com.demo.zyt.modules.app.config.ExecutorTask;
import com.demo.zyt.modules.app.entity.AreaEntity;
import com.demo.zyt.modules.app.entity.WxOrderEntity;
import com.demo.zyt.modules.app.entity.WxQrcodeEntity;
import com.demo.zyt.modules.app.entity.WxUserEntity;
import com.demo.zyt.modules.app.service.AreaService;
import com.demo.zyt.modules.app.service.SysConfigService;
import com.demo.zyt.modules.app.service.WxApplyAllianceService;
import com.demo.zyt.modules.app.service.WxInviteService;
import com.demo.zyt.modules.app.service.WxQrcodeService;
import com.demo.zyt.modules.app.service.WxUserPointTrackService;
import com.demo.zyt.modules.app.service.WxUserService;
import com.demo.zyt.modules.app.utils.ImageUtils;
import com.demo.zyt.modules.app.utils.WeChatUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 对应小程序“我的”的功能
 * @author ebusu
 *
 */
@RestController
@RequestMapping("/app/user")
@Slf4j
public class AppUserController {
	
	@Autowired
	private WxUserService wxUserService;
	
	@Autowired
	private SmsUtils smsUtils;
	
	@Autowired
	private RedisUtils redisUtils;
	
	@Autowired
	private SysConfigService sysConfigService;
	
	@Autowired
	private WxUserPointTrackService wxUserPointTrackService;
	
	@Autowired
	private WxInviteService wxInviteService;
	
	@Autowired
	private WxApplyAllianceService wxApplyAllianceService;
	
	@Autowired
	private AccessTokenStore accessTokenStore;
	
	@Value(value = "${wechat.qrCodePath}")
	private String qrCodePath;
	
	@Autowired
	private WxQrcodeService wxQrcodeService;
	
	@Autowired
	private AreaService areaService;
	/**
	 * 发送短信验证码
	 * 1. 验证当前用户是否已绑定手机号
	 * 2. 验证手机号格式
	 * 3. 验证手机号在系统是否存在, 重复绑定
	 * 4. 生产随机码, 存到缓存, 过期时间为sys_config中配置
	 */
	@GetMapping("/verifyCode/{phone}")
	@Login
	public R sendSms(@PathVariable("phone") String phone , @RequestAttribute("userId") Integer userId) {
		
		if ( !this.smsUtils.isPhone(phone) ) {
			throw new RRException(AppResultEnum.PHONE_FORMAT_ERROR);
		}
		
		this.wxUserService.checkUserPhone(phone, userId);
		
		String verifyCodeInRedis = this.smsUtils.createVerifyCode();
		
		this.redisUtils.set(RedisKeys.getSms(phone), verifyCodeInRedis, 
				Long.parseLong(this.sysConfigService.selectById(ConfigConstant.SMS_EXPIRE_TIME).getParamValue()) * 60);
		
		this.smsUtils.sendSms(phone, verifyCodeInRedis);
		
		return R.ok();
	}

	/**
	 * 绑定手机号
	 * 1. 验证当前用户是否已绑定手机号
	 * 2. 验证手机号格式
	 * 3. 验证手机号在系统是否存在, 重复绑定
	 * 4. 短信验证密是否正确
	 * 5. 验证码是否过期
	 * 6. 给当前用户增加积分
	 */
	@PostMapping("/bind/mobile")
	@Login
	public R bindMobile(@RequestBody WxUserDTO wxUserDTO , @RequestAttribute("userId") Integer userId) {
		
		if ( wxUserDTO == null || StringUtils.isEmpty(wxUserDTO.getMobile()) || StringUtils.isEmpty(wxUserDTO.getVerifyCode())) {
			throw new RRException(AppResultEnum.USER_ARG_ERROR);
		}
		
		if ( !this.smsUtils.isPhone(wxUserDTO.getMobile()) ) {
			throw new RRException(AppResultEnum.PHONE_FORMAT_ERROR);
		}
		
		this.wxUserService.checkUserPhone(wxUserDTO.getMobile(), userId);
		
		String verifyCodeInRedis = this.redisUtils.get(RedisKeys.getSms(wxUserDTO.getMobile()));
		
		if ( StringUtils.isEmpty(verifyCodeInRedis)) {
			throw new RRException(AppResultEnum.VERIFY_CODE_EXPIRE);
		}
		
		if ( !verifyCodeInRedis.equals(wxUserDTO.getVerifyCode())) {
			throw new RRException(AppResultEnum.VERIFY_CODE_ERROR);
		}
		
		this.wxUserService.bindPhone(userId, wxUserDTO);
		
		return R.ok();
	}
	
	/**
	 * 获取当前用户基本信息
	 * @param userEntity
	 * @return
	 */
	@GetMapping("/info")
	@Login
	public R getCurrentUserInfo(@LoginUser WxUserEntity userEntity) {
		
		userEntity.setFansCount(this.wxInviteService.count(userEntity.getUserid()));
		String shareTitle = this.sysConfigService.selectById(ConfigConstant.SHARE_DEFAULT_TITLE).getParamValue();
		return R.ok().put("userEntity", userEntity).put("shareTitle", shareTitle);
	}
	
	/**
	 * 积分使用详情
	 * @param userEntity
	 * @return
	 */
	@GetMapping("/point/track/list")
	@Login
	public R userPointTrackList(@RequestAttribute("userId") Integer userId, @RequestParam Map<String, Object> params) {
		
		return R.ok().put("pointTrackList", this.wxUserPointTrackService.getUserPointTrackList(userId, params));
	}
	
	/**
	 * 获取当前用户粉丝列表
	 * @param userEntity
	 * @return
	 */
	@GetMapping("/invite/list")
	@Login
	public R userInviteList(@RequestAttribute("userId") Integer userId, @RequestParam Map<String, Object> params) {
		
		return R.ok().put("inviteList", this.wxInviteService.getUserInviteList(userId, params));
	}
	
	@Autowired
	private ExecutorTask executorTask;
	/**
	 * 导出当前用户粉丝列表
	 * @param userEntity
	 * @return
	 */
	@PostMapping("/invite/export/list")
	@Login
	public R exportUserInviteList(@RequestAttribute("userId") Integer userId, @RequestBody WxInvitedEmailDTO dto) {
		
		
		
		List<WxUserEntity> userEntities = this.wxInviteService.getAllUserInviteList(userId);
		
		try {
			
			// response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("inviteList.xls", "utf-8"));
			
			HSSFWorkbook workbook = new HSSFWorkbook();
			
			HSSFSheet sheet = workbook.createSheet("粉丝导出结果");
			
			Row headerRow = sheet.createRow(0);
			
			String[] headers = new String[]{"用户昵称", "手机号", "性别", "国家", "省份", "城市", "是否vip", "是否加盟商", "创建日期"};

			for (int headerIndex = 0; headerIndex < headers.length; headerIndex++) {

				Cell headerCell = headerRow.createCell(headerIndex);

				headerCell.setCellValue(headers[headerIndex]);

			}
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

			int dataIndex = 1;
			
			for (WxUserEntity wxUserEntity : userEntities) {

				Row dataRow = sheet.createRow(dataIndex);

				Cell nickNameCell = dataRow.createCell(0);

				nickNameCell.setCellValue(wxUserEntity.getNickname());

				Cell mobileCell = dataRow.createCell(1);

				mobileCell.setCellValue(wxUserEntity.getMobile());

				Cell sexCell = dataRow.createCell(2);
				
				if ( wxUserEntity.getSex() != null ) {
					sexCell.setCellValue(wxUserEntity.getSex() == 1 ? "男": "女");
				} else {
					sexCell.setCellValue("");
				}

				Cell courtyCell = dataRow.createCell(3);

				courtyCell.setCellValue(wxUserEntity.getCountry());

				Cell provinceCell = dataRow.createCell(4);

				provinceCell.setCellValue(wxUserEntity.getProvince());

				Cell counrtyCell = dataRow.createCell(5);

				counrtyCell.setCellValue(wxUserEntity.getCountry());

				Cell isVipCell = dataRow.createCell(6);

				isVipCell.setCellValue(wxUserEntity.getIsVip() == 1 ? "是": "否");
				
				Cell isAllianceBusinessCell = dataRow.createCell(7);

				isAllianceBusinessCell.setCellValue(wxUserEntity.getIsAllianceBusiness() == 1 ? "是": "否");
				
				Cell createdDateCell = dataRow.createCell(8);

				createdDateCell.setCellValue(sdf.format(wxUserEntity.getCreatedDate()));

				dataIndex++;
			}
			
			String filePath = this.qrCodePath + System.currentTimeMillis() + ".xls";
			
			log.info("file path is {}" , filePath);
			
			File file = new File(filePath);
			
			FileOutputStream fos = new FileOutputStream(file);

			workbook.write(fos);

			workbook.close();

			fos.flush();

			fos.close();
			
			executorTask.sendAttachmentsMail(dto.getEmail(), "高考数据通粉丝导出邮件", "您好, 附件是您本次导出的Excel文件.", filePath);
			
			return R.ok();
			
		} catch ( Exception e ) {
			throw new RRException(AppResultEnum.SYSTEM_ERROR);
		}
	}
	
	/**
	 * 申请成为加盟商
	 * 1. 验证当前用户是否已绑定手机号
	 * 2. 保存提交的数据, 等待审核
	 */
	@PostMapping("/apply/alliance")
	@Login
	public R applyAlliance(@RequestBody WxApplyAllianceDTO wxApplyAllianceDTO , @RequestAttribute("userId") Integer userId) {
		
		if ( wxApplyAllianceDTO == null || StringUtils.isEmpty(wxApplyAllianceDTO.getName())) {
			throw new RRException(AppResultEnum.USER_ARG_ERROR);
		}
		
		wxApplyAllianceDTO.setUserid(userId);
		
		this.wxApplyAllianceService.save(wxApplyAllianceDTO);
		
		return R.ok();
	}
	
	/**
	 * 生成二维码
	 */
	@PostMapping("/qrcode/create")
	@Login
	public R createQrCode(@RequestAttribute("userId") Integer userId, @RequestBody WxQrcodeDTO wxQrcodeDTO) {
		
		
		if (wxQrcodeDTO == null || StringUtils.isEmpty(wxQrcodeDTO.getName())) {
			throw new RRException(AppResultEnum.USER_ARG_ERROR);
		}
		
		this.wxQrcodeService.checkQrCodeName(userId,wxQrcodeDTO.getName());
		
		WxQrcodeEntity wxQrcodeEntity = new WxQrcodeEntity();
		
		wxQrcodeEntity.setCreatedDate(new Date());
		wxQrcodeEntity.setName(wxQrcodeDTO.getName());
		wxQrcodeEntity.setUserid(userId);
		
		this.wxQrcodeService.insert(wxQrcodeEntity);
		
		R r = new R();
		
		String qrCodeBase64Image = "";
		
		String imagePath = qrCodePath + userId + "/" + wxQrcodeEntity.getId() + ".png";
		
		try {
			
			if (StringUtils.isEmpty( this.accessTokenStore.getAccessToken() )) {
				this.accessTokenStore.setAccessToken(WeChatUtils.getAccessToken());
			}
		
			qrCodeBase64Image = WeChatUtils.createQrCode(this.accessTokenStore.getAccessToken(), userId, imagePath, wxQrcodeEntity.getId());
			
			r = R.ok();
			
			r.put("image", qrCodeBase64Image);
		} catch ( Exception e ){
			log.error(e.getMessage());
			
			throw new RRException(AppResultEnum.SYSTEM_ERROR);
		}
		
		wxQrcodeEntity.setImage(imagePath);
		this.wxQrcodeService.updateById(wxQrcodeEntity);
		
		return r;
		
	}
	
	/**
	 * 我的二维码列表
	 */
	@GetMapping("/qrcode/list")
	@Login
	public R qrCodeList(@RequestAttribute("userId") Integer userId, @RequestParam Map<String, Object> params) {
		
		params.put("userid", userId);
		
		PageUtils page = this.wxQrcodeService.queryByCondition(params);
		
		return R.ok().put("page", page);
		
	}
	
	/**
	 * 我的二维码详情页
	 */
	@GetMapping("/qrcode/detail/{id}")
	@Login
	public R qrCodeList(@RequestAttribute("userId") Integer userId, @PathVariable(value = "id") String id) {
		
		WxQrcodeEntity wxQrcodeEntity = this.wxQrcodeService.selectById(Integer.parseInt(id));
		
		R r = new R();
		
		String qrCodeBase64Image = "";
		
		String imagePath = qrCodePath + userId + "/" + wxQrcodeEntity.getId() + ".png";
		
		try {
		
			qrCodeBase64Image = ImageUtils.getImgStr(imagePath);
			
			r = R.ok();
			
			r.put("image", qrCodeBase64Image);
			
			r.put("qrCodeEntity", wxQrcodeEntity);
		} catch ( Exception e ){
			log.error(e.getMessage());
			
			throw new RRException(AppResultEnum.SYSTEM_ERROR);
		}
		
		
		return r;
		
	}
	
	/**
	 * 获取地区
	 */
	@GetMapping("/area/list")
	@Login
	public R getArea(@RequestAttribute("userId") Integer userId, HttpServletRequest request) {
		
		String pid = request.getParameter("pid");
		
		String valueIsTitle = request.getParameter("valueIsTitle");
		
		List<AreaEntity> areaEntities = this.areaService.selectByPid(pid);
		
		List<AreaSelectDTO> areaSelectDTOs = new ArrayList<>(areaEntities.size());
		
		List<AreaNoHaveValueDTO> areaNoHaveValueDTOs = new ArrayList<>(areaEntities.size());
		
		if ( !areaEntities.isEmpty() ) {
			
			if ( StringUtils.isEmpty(valueIsTitle)) {
				
				areaEntities.forEach(item -> areaSelectDTOs.add(new AreaSelectDTO(item.getId(), item.getName())));
				
				return R.ok().put("areaList", areaSelectDTOs);
				
			} else {
				
				areaEntities.forEach(item -> areaNoHaveValueDTOs.add(new AreaNoHaveValueDTO(item.getName(), item.getName())));
				
				return R.ok().put("areaList", areaNoHaveValueDTOs);
				
			}
			
		}
		
		return R.ok().put("areaList", areaSelectDTOs);
		
	}
	
	/**
	 * 分享成功之后增加积分
	 */
	@GetMapping("/point/share")
	@Login
	public R getArea(@RequestAttribute("userId") Integer userId) {
		
		this.wxUserService.addUserPoint(userId);
		
		return R.ok();
		
	}
}
